package com.niodata.dp.task.entity.v2;

import com.niodata.dp.task.JobTypeParamSchemasV2;
import com.niodata.dp.task.entity.PackageParam;
import com.niodata.dp.task.entity.PackageParams;
import com.niodata.dp.task.entity.ParamType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.Setter;

/**
 * package params v2,support param groups.
 */
@Setter
@Getter
public class PackageParamsV2 {

  private String title;
  private List<PackageParamGroup> groups;

  public static class PackageParamGroup {

    public String name;
    public String description;
    public String type = "GROUP";
    public List<PackageParamV2> relatedParams = Collections.emptyList();

    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }

    public String getDescription() {
      return description;
    }

    public void setDescription(String description) {
      this.description = description;
    }

    public String getType() {
      return type;
    }

    public void setType(String type) {
      this.type = type;
    }

    public List<PackageParamV2> getRelatedParams() {
      return relatedParams;
    }

    public void setRelatedParams(
        List<PackageParamV2> relatedParams) {
      this.relatedParams = relatedParams;
    }
  }

  public static class PackageParamV2 {

    public String name;
    public String description;
    public String defaultValue;
    public boolean required;
    public boolean userSetAble = true;
    public boolean password;
    public boolean modifiable = true;
    public String type = "INPUT";
    public ParamType dataType = ParamType.STRING;

    public List<Object> relatedParams = Collections.emptyList();

    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }

    public String getDescription() {
      return description;
    }

    public void setDescription(String description) {
      this.description = description;
    }

    public String getDefaultValue() {
      return defaultValue;
    }

    public void setDefaultValue(String defaultValue) {
      this.defaultValue = defaultValue;
    }

    public boolean isRequired() {
      return required;
    }

    public void setRequired(boolean required) {
      this.required = required;
    }

    public boolean isUserSetAble() {
      return userSetAble;
    }

    public void setUserSetAble(boolean userSetAble) {
      this.userSetAble = userSetAble;
    }

    public boolean isPassword() {
      return password;
    }

    public void setPassword(boolean password) {
      this.password = password;
    }

    public boolean isModifiable() {
      return modifiable;
    }

    public void setModifiable(boolean modifiable) {
      this.modifiable = modifiable;
    }

    public String getType() {
      return type;
    }

    public void setType(String type) {
      this.type = type;
    }

    public ParamType getDataType() {
      return dataType;
    }

    public void setDataType(ParamType dataType) {
      this.dataType = dataType;
    }

    public List<Object> getRelatedParams() {
      return relatedParams;
    }

    public void setRelatedParams(List<Object> relatedParams) {
      this.relatedParams = relatedParams;
    }

    public static PackageParamV2 buildFromPackageParam(PackageParam param) {
      PackageParamV2 v2 = new PackageParamV2();
      v2.userSetAble = param.isUserSetAble();
      v2.name = param.getName();
      v2.defaultValue = param.getDefaultValue();
      v2.description = param.getDescription();
      v2.modifiable = param.isUserSetAble();
      v2.password = false;
      v2.relatedParams = Collections.EMPTY_LIST;
      v2.required = param.isRequired();
      v2.type = "INPUT";
      v2.dataType = param.getType();
      return v2;
    }
  }


  /**
   * 遗留兼容老的参数格式,后期迭代将移除.
   *
   * @param params params
   * @return paramsv2
   */
  public static PackageParamsV2 buildFromPackageParams(PackageParams params) {
    PackageParamsV2 v2 = new PackageParamsV2();
    v2.setTitle("PluginConfig");
    List<PackageParamGroup> groups = new ArrayList<PackageParamGroup>();
    v2.setGroups(groups);
    PackageParamGroup group = new PackageParamGroup();
    group.name = "基础配置";
    groups.add(group);
    List<PackageParamV2> relatedParams
        = params.getParamSchemas().stream().map(x -> {
          return PackageParamV2.buildFromPackageParam(x);
        })
        .collect(Collectors.toList());
    List<PackageParamV2> runTimeParams = new ArrayList<>();
    group.relatedParams = relatedParams;
    return v2;
  }

  /**
   * 遗留兼容老的参数格式,后期迭代将移除.
   *
   * @param params params
   * @return paramsv2
   */
  public static PackageParamsV2 buildGroupedParams(PackageParamsV2 params, String jobType,
      String lang) {
    if (params.getGroups().size() > 1) {
      return params;
    }
    PackageParamGroup runTimeGroup =
        JobTypeParamSchemasV2.getJobTypeParamSchemas(jobType, lang);
    Set<String> runTimeKeys = new HashSet<>();
    runTimeGroup.relatedParams.forEach(x -> {
      runTimeKeys.add(x.name);
    });
    PackageParamsV2 v2 = new PackageParamsV2();
    v2.setTitle("PluginConfig");
    List<PackageParamV2> runTimeGrps = new ArrayList<>();
    for (PackageParamV2 p : params.getGroups().get(0).relatedParams) {
      if (runTimeKeys.contains(p.name)) {
        runTimeGrps.add(p);
      }
    }
    runTimeGroup = new PackageParamGroup();
    runTimeGroup.name = "运行环境配置";
    runTimeGroup.description = "运行环境配置";
    runTimeGroup.relatedParams = runTimeGrps;
    List<PackageParamGroup> groups = new ArrayList<PackageParamGroup>();
    groups.add(runTimeGroup);
    v2.setGroups(groups);
    List<PackageParamV2> grps = new ArrayList<>();
    for (PackageParamV2 p : params.getGroups().get(0).relatedParams) {
      if (!runTimeKeys.contains(p.name)) {
        grps.add(p);
      }
    }
    PackageParamGroup group = new PackageParamGroup();
    group.name = "应用配置";
    group.relatedParams = grps;
    groups.add(group);
    return v2;
  }

  public static void filterOutUserNotSetAble(PackageParamsV2 params) {
    params.getGroups().forEach(group -> {
      List<PackageParamsV2.PackageParamV2> ps =
          group.relatedParams.stream().filter(
              p -> {
                return p.userSetAble;
              }).collect(Collectors.toList());
      group.relatedParams = ps;
    });
  }
}
